package Shapes;
import processing.core.*;
import processing.xml.*;

import java.applet.*;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.MouseEvent;
import java.awt.event.KeyEvent;
import java.awt.event.FocusEvent;
import java.awt.Image;
import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import java.util.zip.*;
import java.util.regex.*;

public class Particlesystem extends shape {

	/**
	 * Simple Particle System by Daniel Shiffman.
	 * 
	 * Particles are generated each cycle through draw(), fall with gravity and
	 * fade out over time A ParticleSystem object manages a variable size
	 * (ArrayList) list of particles.
	 */

	ParticleSystem ps;
	
	public Particlesystem(PApplet p) {
		super(p);
		// TODO Auto-generated constructor stub
	}


	public void setup(int number, PVector ori, PVector des) {
		
		ps = new ParticleSystem(number, ori, des);
		parent.smooth();
	}

	public void draw() {
		
		ps.run();
       //ps.addParticle(mouseX, mouseY,30,30);
	}

	// A simple Particle class

	class Particle {
		PVector loc;
		PVector des;
		PVector vel_dir;
		PVector acc;
		float v = 1.0f; // the speed of transportation
		float r;
		float timer;  // the food empire date
		
		// Another constructor (the one we are using here)
		Particle(PVector l, PVector d) {
			acc = new PVector(0, 0.05f, 0);
	//		this.vel_dir = new PVector(random(-1, 1), random(-2, 0), 0);

			this.loc = l.get();
			this.des = d.get();
			this.r = 10.0f;
			this.timer = 1000.0f;
			
			this.vel_dir = d.get();
			this.vel_dir.sub(loc);
			this.vel_dir.normalize();
		}

		public void setVector(float v){
			this.v = v;
			this.vel_dir.add(v, v, v);
		}
		public void setTime(float t){
			this.timer = t;
		}
		
		public void run() {
			update();
			render();
		}

		// Method to update location
		public void update() {
		//	vel_dir.add(acc);
			loc.add(vel_dir);
			timer -= 1.0f;
		}

		// Method to display, if you don't like ellipse, you can change it here
		public void render() {
			parent.ellipseMode(parent.CENTER);
			parent.stroke(255, timer);
			parent.fill(100, timer);
			parent.ellipse(loc.x, loc.y, r, r);
			displayVector(vel_dir, loc.x, loc.y, 10);
		}

		// Is the particle still useful?
		public boolean dead() {
			PVector templ = des.get();
			templ.sub(loc);
			templ.normalize();
			if(templ.x == -vel_dir.x){
				return false;
			}
			
			if (timer <= 0.0f) {
				return true;
			} else {
				return false;
			}
		}

		public void displayVector(PVector v, float x, float y, float scayl) {
			parent.pushMatrix();
			float arrowsize = 4;
			// Translate to location to render vector
			parent.translate(x, y);
			parent.stroke(255);
			// Call vector heading function to get direction (note that pointing
			// up is a heading of 0) and rotate
			parent.rotate(v.heading2D());
			// Calculate length of vector & scale it to be bigger or smaller if
			// necessary
			float len = v.mag() * scayl;
			// Draw three lines to make an arrow (draw pointing up since we've
			// rotate to the proper direction)
			parent.line(0, 0, len, 0);
			parent.line(len, 0, len - arrowsize, +arrowsize / 2);
			parent.line(len, 0, len - arrowsize, -arrowsize / 2);
			parent.popMatrix();
		}

	}

	// A class to describe a group of Particles
	// An ArrayList is used to manage the list of Particles

	class ParticleSystem {

		ArrayList particles; // An arraylist for all the particles
		PVector origin; // An origin point for where particles are born
		PVector destination; // an destination point for where the particles are
								// dead

		ParticleSystem(int num, PVector v1, PVector v2) {
			particles = new ArrayList(); // Initialize the arraylist
			origin = v1.get(); // Store the origin point
			destination = v2.get();
			for (int i = 0; i < num; i++) {
				particles.add(new Particle(origin, destination)); // Add "num" amount of
														// particles to the
														// arraylist
			}
		}

		public void setBoundary(int x1, int y1, int x2, int y2) {

		}

		public void run() {
			// Cycle through the ArrayList backwards b/c we are deleting
			for (int i = particles.size() - 1; i >= 0; i--) {
				Particle p = (Particle) particles.get(i);
				p.run();
				if (p.dead()) {
					particles.remove(i);
				}
			}
		}

		public void addParticle() {
			particles.add(new Particle(origin,destination));
		}

		public void addParticle(float x1, float y1, float x2, float y2) {
			particles.add(new Particle(new PVector(x1, y1), new PVector(x2,y2)));
		}

		public void addParticle(Particle p) {
			particles.add(p);
		}

		// A method to test if the particle system still has particles
		public boolean dead() {
			if (particles.isEmpty()) {
				return true;
			} else {
				return false;
			}
		}

	}

}
